#!/usr/bin/env python
# -*- coding: utf-8 -*-
#import sys, os
try:
	import pygtk
	pygtk.require("2.0")
except:
	pass
try:
	import gtk
	import gtk.glade
	try:
		import pynotify
		NOTIFY_ENABLED = True
	except:
		NOTIFY_ENABLED = False
except:
	sys.exit(1)
#import psyco
import time
import threading
import sys
#psyco.full()

from gui.ConnectionDialog import ConnectDialog
from gui.FavoritesDialog import FavoritesDialog
from gui.ConnectionManager import ConnectionManager
from gui.AboutDialog import AboutDialog
from gui.MagnetDialog import MagnetDialog
from gui.pages.SettingsPage import SettingsPage
from gui.Pager import Pager
from gui.pages.server_page import ServerPage
#from gui.pages.FileListPage import FileListPage
from gui.pages.FileListPage import NewStyleFileListPage as FileListPage
from gui.pages.FindPage import FindPage
from gui.pages.PrivatePage import PrivatePage
from gui.pages.QueuePage import QueuePage
from core.dcpp import DCPP
from core.base import DCPPPart, DCPPEvent, start_new_thread
from xml.sax import make_parser
from xml.sax.handler import ContentHandler

import urllib2
import os
# Non-POSIX Systems
if os.getenv("HOME") == None:
	if os.getenv("USERPROFILE") != None:
		os.environ['HOME'] = os.getenv("USERPROFILE")
from thread import start_new_thread
from gui.base import gtk_lock_required
class SaxHandler(ContentHandler):
        """ Callback class for SAX parser """
        def __init__(self):
                self.dir_stack = list()
                self.dir_stack.append('root')
                self.filelist = {}
                self.filelist['/root'] = list()
                self.chars = ""

        def _getCurPath(self):
                str = ""
                for i in self.dir_stack:
                        str = str + '/' + i
                return str

        def startElement(self,name,attrs):
                """ Handle for element begin """
                if name == 'Directory':
                        dirname = attrs.get('Name').encode('utf-8')
                        self.filelist[self._getCurPath()].append((0, dirname))
                        self.dir_stack.append(dirname)
                        self.filelist[self._getCurPath()] = list()
                elif name == 'File':
                        filename = attrs.get('Name').replace("&amp;","&").encode('utf-8')
                        filesize = attrs.get('Size').encode('utf-8')
                        filetth = attrs.get('TTH').encode('utf-8')
                        self.filelist[self._getCurPath()].append((1, filename, filesize, filetth))

        def endElement(self,name):
                """ Handle for finished element """
                if name == 'Directory':
                        self.dir_stack.pop()

        def characters (self,ch):
                """ Handle for character data """
                sch = ch.lstrip()
                if not sch == "":
                        self.chars = sch

class GtkDCPPGUI(DCPPPart):
	def _fastConnect(self,widget, event, slot):
		self.wtree.get_widget(widget).connect(event, slot)

	def _connectEvents(self):
		self.window.connect('destroy',self.main_quit)
		self._fastConnect("toolConnect", 'clicked', self._connectDialog.show)
		self._fastConnect("toolQuit",'clicked',self.main_quit)
		self._fastConnect("menuConnect",'activate',self._connectDialog.show)
		self._fastConnect('menuQuit','activate', self.main_quit)
		self._fastConnect('menuAbout', 'activate', self.about_show)
		self._fastConnect("toolFavorites","clicked", self._favoritesDialog.show)
		self._fastConnect("toolSettings","clicked", self._onsettings)
		self._fastConnect("menuSettings", "activate", self._onsettings)
		self._fastConnect('toolSearch', 'clicked', self._onsearch)
		self._fastConnect("toolOwn", "clicked", self._ownfiles)
		self._fastConnect('toolQueue', 'clicked', self._queueshow)
		self._fastConnect("status_exit", 'activate', self.main_quit)
		self._fastConnect("status_normal_size", 'activate', self.status_show)
		self._fastConnect("status_open_magnet", 'activate', self._openmagnet)
		self._fastConnect('menu_open_magnet', 'activate', self._openmagnet)
	
	def _openmagnet(self, *args, **kwargs):
		self._magnetDialog.show()

	def status_show(self, *args, **kwargs):
		if not self._appstatus:
			self.window.show()
			self._appstatus = 1

	def _queueshow(self, *args, **kwargs):
		self._pager.add(QueuePage(self))

	def _ownfiles(self, *args, **kwargs):
		self._pager.add(FileListPage(self, self.settings.get('nickname'), os.path.join(os.getenv("HOME"), ".simpledcpp/files.xml.bz2")))

	def _onsearch(self, *args, **kwargs):
		self._pager.add(FindPage(self))

	def about_show(self, *args, **kwargs):
		self._aboutDialog.show()

	def __init__(self):
	#	pynotify.init("Basics")
		self._dcpp = DCPP()
		self.queue = self._dcpp.queue
		self.Events = self._dcpp.Events
		self.settings = self._dcpp.settings
		self.filelist = self._dcpp.filelist
		self.Events.Subscribe("ON_SYSTEM_SHUTDOWN",self.main_quit)
		self.Events.Subscribe("ON_ALREADY_DOWNLOAD", self._readyfile)
		self.Events.Subscribe("CORRUPTED_FILE", self._corrupted)
		self.Events.Subscribe("OPEN_PRIVATE", self._openprivate)
		self.Events.Subscribe("ON_PRIVATE_MESSAGE", self._onprivate)
#		self.Events.Subscribe("TRY_OWN_FILELIST", lambda self, event: self.Notify("Попытка скачать свой файллист.", "Действие отменено, если хотите продолжить нажмите кнопку \"Мои файлы\" в верхней панели."))
		self.Events.Subscribe("TRY_OWN_FILELIST", self._tryown)
		self.Events.Subscribe("TASK_ALREADY_IN_QUEUE", self._talready)
		self.Events.Subscribe("QUEUE_IS_EMPTY", self._qempty)
		self.Events.Subscribe("GSB", self._gsb)
		self.Events.Subscribe("LSB", self._lsb)
		self.gladefile = os.path.join(os.path.dirname(__file__),"../../glade/main.glade")
		self.wtree = gtk.glade.XML(self.gladefile)
		self.window = self.wtree.get_widget("MainWindow")
		self._pager = Pager(self)
		self._lsb = self.wtree.get_widget("LocalStatusBar")
		self._gsb = self.wtree.get_widget("GlobalStatusBar")
		self._connectDialog = ConnectDialog(self)
		self._favoritesDialog = FavoritesDialog(self)
		self._connectionManager = ConnectionManager(self)
		self._aboutDialog = AboutDialog()
		self._magnetDialog = MagnetDialog(self)
#	self._settingsDialog = SettingsDialog(self)
		self._connectEvents()
		self._statusicon = gtk.StatusIcon()
#		self._statusicon.set_from_stock(gtk.STOCK_NETWORK)
		path_to_status_icon = os.path.join(os.path.dirname(__file__),"../../res/sdcpp.png")
		self._statusicon.set_from_file(path_to_status_icon)
		self._statusicon.set_tooltip("SimpleDC++ Client")
		self._statusicon.connect('activate', self._onactivate)
		self._statusicon.connect('popup-menu', self._statuspopup)
		self._statuspopupmenu = self.wtree.get_widget("StatusPopup")
		self._appstatus = 0
		self.window.show()
		self._favoritesDialog._autoconnect()
#		self._pager.add(FileListPage(self,"n0uk","files.xml.bz2"))
#		self._statusIcon = gtk.StatusIcon()
#		self._statusIcon.set_from_stock(gtk.STOCK_GO_DOWN)
#		self._statusIcon.set_visible(True)
#		self._threadclip = start_new_thread(self.clipboard_catcher)
		self.Event(DCPPEvent("GUI_READY", ()))

	def _onactivate(self, *args, **kwargs):
		if (self._appstatus):
			self.window.hide()
			self._appstatus = 0
		else:
			self.window.show()
			self._appstatus = 1

	def _statuspopup(self, wiget, button, time, data = None):
		self._statuspopupmenu.popup(None, None, None, 3 , time)

	@gtk_lock_required
	def _gsb(self, Event):
		try:
			self._gsb.push(1, Event.userdata[0])
		except:
			pass

	@gtk_lock_required
	def _lsb(self, Event):
		try:
			self._lsb.push(1, Event.userdata[0])
		except:
			pass

	def _qempty(self, *args, **kwargs):
		self.Notify(_("Queue is empty"),_("All files has been downloads."))
	def _tryown(self, Event):
		self.Notify(_("You're trying download own filelist"), _("Canceled. Try to press 'My Files' button at toolbar."))
	def _talready(self, Event):
		task = Event.userdata[0]
		self.Notify(_("Task already in queue"), _("You're trying download file") + "(%s)"%task.localfilename + _("but this file already in queue"))

	@gtk_lock_required
	def _openprivate(self, Event):
		nickname = Event.userdata[0]
		hub = Event.userdata[1]
                for i in self._pager.pages:
                        if i.type == 'private' and i._nickname == nickname:
                                return
		page = PrivatePage(self, nickname, hub)
		self._pager.add(page)

	@gtk_lock_required
	def _onprivate(self, Event):
		try:
			hub, to, fm, mg = Event.userdata
	                for i in self._pager.pages:
        	                if i.type == 'private' and i._nickname == fm:
					try:
						if self._pager._widget.get_nth_page(self._pager._widget.get_current_page()) != i._widget:
							#print "Using underline"
#							text = i._label.get_label()
#							i._label.set_use_underline(True)
#							i._label.set_label(text)
							i._label.set_angle(10)
#					if self._pager._widget.get_current_page() != i:
#						i._label.set_use_underline(True)
					except:
						pass
                	                return
                        if int(self.settings.get("NotifyMessage",1)):
#				nmg = mg.replace("<","&lt;")
#				nmg = nmg.replace(">","&gt;")
				nmg = mg.split(" ",1)[1]
				nmg = nmg.replace("<","&lt;").replace(">","&gt;")
                         	self.Notify(_("New message from user ") +  " %s"%fm,nmg)
#				print fm,nmg

			page = PrivatePage(self, fm, hub)
			self._pager.add(page)
		        # Page don't recieve this event. Force it.
        		page._chatwindow._message(Event)
		except:
			print sys.exc_info()
	
	def _corrupted(self, Event):
		task = Event.userdata[0]
		try:
                        if int(self.settings.get("NotifyFile",1)):
				self.Notify(_("Downloaded file are corrupted."),"%s"%task.localfilename)
                except:
                        print sys.exc_info()

	@gtk_lock_required
	def _readyfile(self, Event):
		task = Event.userdata[0]
		try:
			if int(self.settings.get("NotifyFile",1)):
				self.Notify(_("File already downloaded"),"%s"%task.localfilename)
		except:
			print sys.exc_info()
		if task.TTH == 'files.xml.bz2':
			try:
				if task.METADATA != None and task.METADATA.startswith("DOWNLOAD_DIR:"):
					self.__downloaddir = None
					nickname = task.METADATA.split(' ',2)[1]
					goal_dir = task.METADATA.split(' ',2)[2]
					self._loadFileList(task.localfilename)
					self._fillpath = '/root/'
					path = "/root/" + goal_dir.replace("\\","/")
#					print path, nickname
					self.RecursiveDownload(path, nickname)
				elif task.METADATA != None and task.METADATA.startswith("DOWNLOAD_DIR_TO:"):
					goal_dir = task.METADATA.split(':',3)[1]
					download_to = task.METADATA.split(':',3)[2]
					nickname = task.METADATA.split(':',3)[3]
					self.__downloaddir = download_to
					self._loadFileList(task.localfilename)
					self._fillpath = '/root/'
					path = '/root/' + goal_dir.replace('\\','/')
#					print nickname, download_to, goal_dir
					self.RecursiveDownload(path, nickname)

				elif task.METADATA != None and task.METADATA.startswith("EXPANDTTH:"):
					self._pager.add(FileListPage(self, 
							task.sources.sources[0].nickname,
							task.localfilename,
							task.METADATA.split(':')[1]))
				else:
					self._pager.add(FileListPage(self, task.sources.sources[0].nickname, task.localfilename))
				os.remove(task.localfilename)
			except:
				print sys.exc_info()

        def RecursiveDownload(self, path, nickname):
#		print path
#		print self._fillpath
		try:
                	if self._goalfilelist.has_key(path):
                        	for i in self._goalfilelist[path]:
                                	if int(i[0]) == 1:
#                                        	print "Download file %s to %s (%s)"%(i[3], path.replace(self._fillpath, "") + '/' + i[1], i[2])
						if self.__downloaddir != None:
							self.RequestTask(i[3] , path.replace(self._fillpath, "") + '/' + i[1], i[2], nickname, "DOWNLOADTO:%s"%self.__downloaddir)
						else:
	                                    	        self.RequestTask(i[3] , path.replace(self._fillpath, "") + '/' + i[1], i[2], nickname)
                               	 	else:
                                        	self.RecursiveDownload(path + '/' + i[1], nickname)
		except:
			print sys.exc_info()

	def RequestTask(self, file, localfilename, filesize, nickname, METADATA = None):
                self.Event(DCPPEvent("NEED_TASK", (file, localfilename, int(filesize), nickname, METADATA)))

        def _loadFileList(self, filename):
		temp = '/tmp'
		if os.getenv('TEMP') != None and os.path.isdir(os.getenv('TEMP')):
			temp = os.getenv('TEMP')
                os.system('bzcat "%s" > %s/loadfilelist.tmp'%(filename,temp))
                curHandler = SaxHandler()#(self.treestore,root_elem)
                parser = make_parser()
                parser.setContentHandler(curHandler)
                try:
                        parser.parse(open('%s/loadfilelist.tmp'%temp))
                except IOError:
			pass
#                       print "Error while parsing %s"%'/tmp/loadfilelist.tmp'
                os.remove('%s/loadfilelist.tmp'%temp)
                self._goalfilelist = curHandler.filelist


	def main_quit(self, *args, **kwargs):
		self._dcpp.stop()
#		self._threadclip.kill()
		gtk.main_quit()

	def _onsettings(self, *args, **kwargs):
		for i in self._pager.pages:
			if i.type == 'Settings':
				return
		self._pager.add(SettingsPage(self))

	def _connectTo(self, server):
		#self._dcpp.ConnectTo((server,411))
		name = server
		for i in self._pager.pages:
			if i.name == name:
				return
		self._pager.add(ServerPage(self, server))
		self._dcpp.ConnectTo((server, 411))

	def _reconnectTo(self, server):
		self._dcpp.ConnectTo((server, 411))

	def stop(self, *args, **kwargs):	
		#self.main_quit()'
		gtk.main_quit()
	
	def Event(self, *args, **kwargs):
		self._dcpp.Event(*args,**kwargs)


def main(*args, **kwargs):
	global NOTIFY_ENABLED
	GUI = GtkDCPPGUI()
	try:
		if NOTIFY_ENABLED:
			pynotify.init("Basics")
		gtk.gdk.threads_init()
		gtk.gdk.threads_enter()
		gtk.main()
		gtk.gdk.threads_leave()
	except:
		print _("Exiting.")
		sys.exit(1)
#if __name__ == "__main__":
#	GUI = GtkDCPPGUI()
#	try:
#		pynotify.init("Basics")
#		gtk.gdk.threads_init()
#		gtk.gdk.threads_enter()
#		gtk.main()
#		gtk.gdk.threads_leave()
#	except:
#		print "Exiting."
#		sys.exit(1)


